package {
	import com.adobe.scenegraph.MaterialStandard;
	import com.adobe.scenegraph.MeshElement;
	import com.adobe.scenegraph.MeshUtils;
	import com.adobe.scenegraph.RenderSettings;
	import com.adobe.scenegraph.RenderTextureReflection;
	import com.adobe.scenegraph.SceneMesh;
	import com.adobe.scenegraph.SceneNode;
	import com.ds.factory.TFFactory;
	import com.ds.ui.LabeledBtn;
	import com.ds.ui.SmartContainer;
	import flash.display.Stage3D;
	
	import flash.display.InteractiveObject;
	import flash.display3D.Context3DRenderMode;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Vector3D;
	import flash.text.TextField;
	import flash.ui.Keyboard;
	
	import rubix.control.Rubix;
	import rubix.data.Sides;
	
	public class RubixCube extends BasicDemo {
		
		private var _cubeBig:SceneNode; // контейнер для кубика-рубика
	
		private var _rubix:Rubix; // кубик-рубик
		
		public function RubixCube(renderMode:String = Context3DRenderMode.AUTO){
			trace("RubixCube!!");
			super(renderMode);
			addEventListener(Event.ADDED_TO_STAGE, addedHandler);
		}
		
		// Создание кнопочек.
		// Т.к. демо-версия просцениума нас сильно подвела
		// с интерактивностью контента (метод pick у сцены 
		// при разных трансформациях работает на так гладко,
		// как хотелось бы), а времени на разборки с лучами
		// у нас нет, то нам прийдется сделать кнопочный
		// интерфейс для нашего кубика.
		// Вращение по цвету грани. Цвет грани определяется
		// цветом центрального квадрата на грани.
		private function initButtons():void {
			// контейнер
			var interfaceContainer:SmartContainer = new SmartContainer();
			interfaceContainer.vertical = true;
			// Кнопки для вращения по часовой стрелке
			var txt:TextField = TFFactory.createTextField();
			txt.text = "CW:";
			interfaceContainer.addChild(txt);
			var btnContainer:SmartContainer = new SmartContainer();
			var side:Object;
			for each (side in Sides.data){
				btnContainer.addChild(new LabeledBtn(side.label, side.color, side.orientation));
			}
			btnContainer.addEventListener(MouseEvent.CLICK, btnContainerMouseClickHandler);
			interfaceContainer.addChild(btnContainer);
			
			// Кнопки для вращения против часовой стрелки
			var txt2:TextField = TFFactory.createTextField();
			txt2.text = "CCW:";
			interfaceContainer.addChild(txt2);
			var btnContainer2:SmartContainer = new SmartContainer();
			
			for each (side in Sides.data){
				btnContainer2.addChild(new LabeledBtn(side.label, side.color, side.orientation));
			}
			btnContainer2.addEventListener(MouseEvent.CLICK, btnContainer2MouseClickHandler);
			interfaceContainer.addChild(btnContainer2);
			
			// Кнопка для поворота случайной грани куба
			var randomBtn:LabeledBtn = new LabeledBtn("Random move");
			randomBtn.addEventListener(MouseEvent.CLICK, randomBtnClickHandler);
			interfaceContainer.addChild(randomBtn);
			
			// Кнопка для отмены хода
			var undoBtn:LabeledBtn = new LabeledBtn("Undo");
			undoBtn.addEventListener(MouseEvent.CLICK, undoBtnPressHandler);
			interfaceContainer.addChild(undoBtn);
			var undoAllBtn:LabeledBtn = new LabeledBtn("Undo All");
			undoAllBtn.addEventListener(MouseEvent.CLICK, undoAllBtnPressHandler);
			interfaceContainer.addChild(undoAllBtn);
			
			interfaceContainer.addEventListener(MouseEvent.MOUSE_OVER, btnContainerMouseOverHandler);
			interfaceContainer.addEventListener(MouseEvent.MOUSE_OUT, btnContainerMouseOutHandler);
			interfaceContainer.x = interfaceContainer.y = 10;
			addChild(interfaceContainer);
		}
		
		// Обработчики событий интерфейса
		protected function undoAllBtnPressHandler(event:MouseEvent):void {
			_rubix.undoAll();
		}
		
		protected function undoBtnPressHandler(event:MouseEvent):void {
			_rubix.undoMove();
		}
		
		
		protected function randomBtnClickHandler(event:MouseEvent):void {
			_rubix.randomMove();
		}
		
		protected function btnContainerMouseOutHandler(event:MouseEvent):void {
			_rubix.highlightSide(null);
		}
		
		protected function btnContainerMouseOverHandler(event:MouseEvent):void {
			var btn:LabeledBtn = event.target as LabeledBtn;
			if (btn){
				_rubix.highlightSide(btn.userData);
			}
		}
		
		private function btnContainerMouseClickHandler(event:MouseEvent):void {
			var btn:LabeledBtn = event.target as LabeledBtn;
			if (btn){
				_rubix.rotate(btn.userData);
			}
		}
		
		private function btnContainer2MouseClickHandler(event:MouseEvent):void {
			var btn:LabeledBtn = event.target as LabeledBtn;
			if (btn){
				_rubix.rotate(btn.userData, -90);
			}
		}
		
		// Тут мы настраиваем камеру
		override protected function resetCamera():void {
			_camera = scene.activeCamera;
			_camera.identity();
			_camera.position = CAMERA_ORIGIN;
			_camera.appendRotation(-15, Vector3D.X_AXIS);
		}
		
		// Метод, в котором создается и настраивается сцена
		override protected function initModels():void {
			// Таким нехитрым образом включается туман. Лучи радости и любви адобовцам!
			instance.backgroundColor.setFromUInt(0x556677);
			instance.primarySettings.fogMode = RenderSettings.FOG_EXP2;
			instance.primarySettings.fogDensity = 2300;
			
			// Создаем и ставим на сцену контейнер кубика-рубика
			_cubeBig = new SceneNode();
			_cubeBig.appendTranslation(0, 0, -15);
			scene.addChild(_cubeBig);
			
			_rubix = new Rubix(_cubeBig);
			//_cubeBig.addChild(_rubix.getView());
			
			// Создаем зеркальный материал для пола
			
			// текстура с отражением 
			var refMap:RenderTextureReflection = new RenderTextureReflection(2048, 2048);
			// нода, которая будет отражаться
			refMap.addSceneNode(scene);
			var mirrorMaterial:MaterialStandard = new MaterialStandard("floor");
			// приписываем материалу текстуру с отражением
			mirrorMaterial.emissiveMap = refMap;
			
			mirrorMaterial.diffuseColor.setFromUInt(0x000000);
			mirrorMaterial.ambientColor.setFromUInt(0x000000);
			mirrorMaterial.specularColor.setFromUInt(0x333333);
			
			// Создаем пол и добавляем его на сцену
			var plane:SceneMesh = MeshUtils.createPlane(200, 200, 20, 20, mirrorMaterial, "floor");
			// "текстура должна знать, где она будет рисоваться" - как сказано в одном из примеров от адоба
			refMap.reflectionGeometry = plane;
			plane.appendTranslation(0, -15, 0);
			scene.addChild(plane);
		
		}
		
		// Основные обработчики событий
		
		// Крутим кубик-рубика при помощи мышки
		override protected function mouseEventHandler(event:MouseEvent, target:InteractiveObject, offset:Point, data:* = undefined):void {
			
			if (offset.x == 0 && offset.y == 0)
				return;
			
			_cubeBig.appendRotation(offset.x, Vector3D.Y_AXIS, _cubeBig.position);
			_cubeBig.appendRotation(offset.y, Vector3D.X_AXIS, _cubeBig.position);
		}
		
		protected function addedHandler(event:Event):void {
			initButtons();
			stage.addEventListener(MouseEvent.CLICK, stage_clickHandler);
		}
		
		// Передаем событие отрисовки кубику
		override protected function onAnimate(t:Number, dt:Number):void {
			_rubix.onAnimate(t, dt);
		}
		
		
		private var currNode:SceneMesh;
		private function stage_clickHandler(event:MouseEvent):void {
			
			if (!scene)
				return;
			
			var x:Number = (event.stageX - width * .5) / width * 2;
			var y:Number = -(event.stageY - height * .5) / height * 2;
			
			var node:SceneMesh = scene.pick( x, y ) as SceneMesh;
			
//			trace(node);
			var key:MeshElement;
			if (node){
				if (currNode){
					if (currNode.elements.length > 0){
						key = currNode.elements[0];
						currNode.materialBindings[key] = null;
					}
				}
				currNode = node;
				if (currNode.elements.length > 0){
					key = currNode.elements[0];
					var mtrl:MaterialStandard = new MaterialStandard("test");
					mtrl.diffuseColor.setFromUInt(0xff0000);
					currNode.materialBindings[key] = mtrl;
				}
				
			}
		}
		
		
	}
}